package com.shop.service.impl;

import com.shop.common.Constants;
import com.shop.exception.BusinessException;
import com.shop.mapper.UserMapper;

import com.shop.model.User;
import com.shop.model.common.SearchPage;
import com.shop.service.MinioService;
import com.shop.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import org.springframework.web.multipart.MultipartFile;

import java.time.LocalDateTime;
import java.util.List;

@Service
@Slf4j
public class UserServiceImpl implements UserService {

    private final UserMapper userMapper;
    @Autowired
    private MinioService minioService;

    public UserServiceImpl(UserMapper userMapper) {
        this.userMapper = userMapper;
    }

    @Override
    public User login(String phone, String password) {
        // 校验手机号
        LogincheckUserPhoneAndPwd(phone, password);
        User user = userMapper.selectByPhone(phone);
        if (user == null || user.getId() == null) {
            throw new BusinessException("手机号未注册");
        }
        // 校验密码，使用md5加密后
        String pass = getPasswordForMd5(password);
        if (!pass.equals(user.getPassword())) {
            throw new BusinessException("密码错误");
        }
        if(user.getStatus()!=1){
            throw new BusinessException("账号异常");
        }
        return user;
    }

    @Override
    public User loginEmail(String email, String password) {
        checkUserEmailAndPwd(email, password);
        User user = userMapper.selectByEmail(email);
        if (user == null || user.getId() == null){
            throw new BusinessException("邮箱未注册");
        }
        String pass = getPasswordForMd5(password);
        if (!pass.equals(user.getPassword())) {
            throw new BusinessException("密码错误");
        }
        if (user.getStatus()!=1){
            throw new BusinessException("账号异常");
        }
        return user;
    }

    @Override
    public void register(User user) {
        if(user==null){
            throw new NullPointerException();
        }
        user.setId(null);
        if(user.getPassword()==null || user.getConfirmPassword()==null){
            throw new BusinessException("密码不能为空");
        }
        checkUserPhoneAndPwd(user.getPhone(), user.getPassword(),user.getUsername());
        if(!user.getPassword().equals(user.getConfirmPassword())){
            throw new BusinessException("两次密码不一致");
        }
        // 是否已经存在
        if (userMapper.selectByPhone(user.getPhone()) != null) {
            throw new BusinessException("手机号已注册");
        }
        if(user.getUsername()==null || user.getUsername().isEmpty()){
            throw new BusinessException("用户名不能为空");
        }
        initUser(user);
        String passwordMd5 = getPasswordForMd5(user.getPassword());
        user.setPassword(passwordMd5);
        userMapper.insertSelective(user);
    }

    @Override
    public User modifyUser(User user) {
        if(user==null){
            throw new BusinessException("未更改用户信息");
        }
        if(user.getPhone()==null||user.getId()==null){
            throw new BusinessException("用户不存在");
        }
        // 校验手机号
        String phone = user.getPhone();
        if (phone == null) {
            throw new BusinessException("登录输入不能为空");
        }
        if (!phone.matches(Constants.Regex.PHONE)) {
            throw new BusinessException("手机号格式错误");
        }
        if (!user.getUsername().matches(Constants.Regex.USERNAME_REGEX)){
            throw new BusinessException("用户名包含字母和数字，不能以数字开头，6-10位");
        }
        User oldUser = userMapper.selectByPrimaryKey(user.getId());
        if(oldUser==null){
            throw new BusinessException("用户不存在");
        }
        if (oldUser.getPhone() == null){
            User checkUserPhone = userMapper.selectByPhone(user.getPhone());
            if (checkUserPhone != null) {
                throw new BusinessException("手机号已注册");
            }
        }else {
            if (!oldUser.getPhone().equals(user.getPhone())) {
                User checkUserPhone = userMapper.selectByPhone(user.getPhone());
                if (checkUserPhone != null) {
                    throw new BusinessException("手机号已注册");
                }
            }
        }
        if(oldUser.getEmail() == null){
            User checkUserEmail = userMapper.selectByEmail(user.getEmail());
            if (checkUserEmail != null) {
                throw new BusinessException("邮箱已注册");
            }
        }else {
            if (!oldUser.getEmail().equals(user.getEmail())) {
                User checkUserEmail = userMapper.selectByEmail(user.getEmail());
                if (checkUserEmail != null) {
                    throw new BusinessException("邮箱已注册");
                }
            }
        }
        String email=user.getEmail();
        if (email != null ){
            if (!user.getEmail().matches(Constants.Regex.EMAIL)){
                throw new BusinessException("邮箱格式错误");
            }
        }
        int num = userMapper.updateByPrimaryKeySelective(user);
        if(num<1){
            throw new BusinessException("用户不存在");
        }
        return userMapper.selectByPhone(user.getPhone());
    }

    @Override
    public String uplaodAvatar(MultipartFile file) throws Exception {
        return minioService.uploadFile(file);
    }

    @Override
    public List<User> searchPage(SearchPage searchPage) {
        int offSet=(searchPage.getPage()-1)* searchPage.getPageSize();
        searchPage.setOffSet(offSet);
        log.info("searchPage:{}", searchPage);
        List<User> list=userMapper.searchPage(searchPage);
        log.info("userList:{}",list);
        return list;
    }

    @Override
    public Integer searchCount(SearchPage searchPage) {
        return userMapper.searchCount(searchPage);
    }

    @Override
    public void userFreeze(Integer id) {
        userMapper.userFreeze(id,0);
    }

    @Override
    public void userUnFreeze(Integer id) {
        userMapper.userFreeze(id,1);
    }

    @Override
    public void blacklistAdd(Integer id) {
        userMapper.userFreeze(id,2);
    }

    @Override
    public void blacklistRemove(Integer id) {
        userMapper.userFreeze(id,1);
    }

    @Override
    public void userDelete(Integer id) {
        userMapper.userFreeze(id,3);
    }


    @Override
    public void changePhone(String newPhone, User user) {
        if (!newPhone.matches(Constants.Regex.PHONE)) {
            throw new BusinessException("手机号格式错误");
        }
        if(!newPhone.equals(user.getPhone())){
            User checkUserPhone = userMapper.selectByPhone(newPhone);
            if (checkUserPhone!=null){
                throw new BusinessException("手机号已注册");
            }
        }
        int a=userMapper.changePhone(newPhone, Math.toIntExact(user.getId()));
        if (a <= 0){
            throw new BusinessException("修改错误");
        }
    }

    @Override
    public Integer deleteByPrimaryKey(Long id) {
        if(id == null){
            throw new BusinessException("账号不存在");
        }
        int a = userMapper.deleteByPrimaryKey(id);
        return a;
    }

    @Override
    public void getChangPassword(User olduser, String password, String confirmPassword, String oldPassword) {
        if (olduser == null || password == null || confirmPassword == null || oldPassword == null) {
            throw new BusinessException("参数不能为空");
        }
        String oldPassMd5 = getPasswordForMd5(oldPassword);
        if (!olduser.getPassword().equals(oldPassMd5)){
            throw new BusinessException("原密码错误，请重新输入！");
        }
        if (!password.matches(Constants.Regex.PASSWORD_REGEX)){
            throw new BusinessException("密码包含字母和数字，并且必须以大写字母开头的6-10位");
        }
        if (!password.equals(confirmPassword)){
            throw new BusinessException("两次密码不一样，请重新输入");
        }
        String passMd5 = getPasswordForMd5(password);
        int a = userMapper.getChangPassword(olduser.getId(),passMd5);
        if (a<=0){
            throw new BusinessException("密码修改错误");
        }
    }

    static void checkUserPhoneAndPwd(String phone, String password, String username) {
        if (phone == null || password == null) {
            throw new BusinessException("登录输入不能为空");
        }
        if (!phone.matches(Constants.Regex.PHONE)) {
            throw new BusinessException("手机号格式错误");
        }
        if (!password.matches(Constants.Regex.PASSWORD_REGEX)) {
            throw new BusinessException("密码包含字母和数字，并且必须以大写字母开头的6-10位");
        }
        if(!username.matches(Constants.Regex.USERNAME_REGEX)){
            throw new BusinessException("用户名包含字母和数字，不能以数字开头，6-10位");
        }
    }
    static void LogincheckUserPhoneAndPwd(String phone, String password) {
        if (phone == null || password == null) {
            throw new BusinessException("登录输入不能为空");
        }
        if (!phone.matches(Constants.Regex.PHONE)) {
            throw new BusinessException("手机号格式错误");
        }
    }

    static void checkUserEmailAndPwd(String email, String password) {
        if (email == null || password == null) {
            throw new BusinessException("登录输入不能为空");
        }
        if (!email.matches(Constants.Regex.EMAIL)) {
            throw new BusinessException("QQ邮箱格式错误");
        }
        if (!password.matches(Constants.Regex.PASSWORD_REGEX)) {
            throw new BusinessException("密码长度不能小于6位");
        }
    }

    static void initUser(User user){
        if(user==null){
            throw new NullPointerException();
        }
        if(user.getId()==null){
            user.setId(0L);
        }
        user.setCreateTime(LocalDateTime.now());
        user.setUpdateTime(LocalDateTime.now());
    }

    static void updateUser(User user){
        if(user==null){
            throw new NullPointerException();
        }
        user.setUpdateTime(LocalDateTime.now());
    }

    static String getPasswordForMd5(String password){
        if(password==null){
            throw new NullPointerException();
        }
        return DigestUtils.md5DigestAsHex(password.getBytes());
    }


}